﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace Sofire.Data.XSql
{
    /// <summary>
    /// XSql 生成工厂。
    /// </summary>
    public class XSqlFactory
    {
        private XSqlDocument _Document;

        /// <summary>
        /// 初始化 <see cref="Sofire.Data.XSql.XSqlFactory"/> 的新实例。
        /// </summary>
        /// <param name="engine">数据库操作引擎。</param>
        public XSqlFactory(QueryEngineBase engine)
        {
            this._Document = new XSqlDocument(engine);
        }

        /// <summary>
        /// 添加子集合。
        /// </summary>
        /// <param name="parent">父节点。</param>
        /// <param name="children">子集合。</param>
        public void AppendChildren(IXSql parent, params IXSql[] children)
        {
            if(children == null || children.Length == 0) return;

            var coll = (parent.Children as XSqlNodeCollection);
            XSqlNodeBase prev = null;
            foreach(XSqlNodeBase child in children)
            {
                if(prev != null)
                {
                    prev.Next = child;
                    child.Previous = prev;
                }
                child.Parent = parent;
                coll.Add(child);
                prev = child;
            }
        }

        /// <summary>
        /// 创建一个文档，并清空当前语法。
        /// </summary>
        /// <param name="children">子集合。</param>
        /// <returns>返回生成的文档。</returns>
        public IXSqlDocument Create(params IXSqlNode[] children)
        {
            foreach(var child in children)
            {
                this._Document.XSqls.Add(child);
            }
            var document = new XSqlDocument(this._Document.Engine);
            document.LoadXml(this._Document.CreateXml());
            this._Document = new XSqlDocument(this._Document.Engine);
            return document;
        }

        #region 语法

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlProcedureNode"/> 的语法。
        /// </summary>
        /// <param name="name">节点的名称。</param>
        /// <param name="cache">缓存的模式。</param>
        /// <param name="ignores">参数忽略列表，可为 null 值。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlProcedureNode"/>。</returns>
        public IXSqlProcedureNode Procedure(string name
            , XSqlCacheMode cache
            , string ignores, params IXSql[] children)
        {
            var node = new XSqlProcedureNode()
            {
                Name = name,
                CacheMode = cache,
                Ignores = ignores,
                Document = this._Document,
            };
            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlNode"/> 的语法。
        /// </summary>
        /// <param name="name">节点的名称。</param>
        /// <param name="cache">缓存的模式。</param>
        /// <param name="ignores">参数忽略列表，可为 null 值。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlNode"/>。</returns>
        public IXSqlNode XSql(string name
            , XSqlCacheMode cache
            , string ignores, params IXSql[] children)
        {
            var node = new XSqlNode()
            {
                Name = name,
                CacheMode = cache,
                Ignores = ignores,
                Document = this._Document,
            };
            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlIfNode"/> 的语法。
        /// </summary>
        /// <param name="test">测试的表达式。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlIfNode"/>。</returns>
        public IXSqlIfNode If(string test
            , params IXSql[] children)
        {
            XSqlIfNode node = new XSqlIfNode()
            {
                Test = test,
                Document = this._Document,
            };

            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlElseNode"/> 的语法。
        /// </summary>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlElseNode"/>。</returns>
        public IXSqlElseNode Else(params IXSql[] children)
        {
            XSqlElseNode node = new XSqlElseNode()
            {
                Document = this._Document,
            };
            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlForeachNode"/> 的语法。
        /// </summary>
        /// <param name="var">循环的初始变量名。</param>
        /// <param name="in">循环的集合参数名。</param>
        /// <param name="index">循环时的索引变量名，可为 null 值。</param>
        /// <param name="trim">移除所有前导匹配项和尾部匹配项，可为 null 值。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlForeachNode"/>。</returns>
        public IXSqlForeachNode Foreach(string var, string @in, string index
            , string trim
            , params IXSql[] children)
        {
            XSqlForeachNode node = new XSqlForeachNode()
            {
                Var = var,
                In = @in,
                Trim = trim,
                Index = index,
                Document = this._Document,
            };
            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlTextNode"/> 的语法。
        /// </summary>
        /// <param name="text">纯文本内容，可为 null 值。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlTextNode"/>。</returns>
        public IXSqlTextNode Text(string text)
        {
            return new XSqlTextNode() { Text = text, Document = this._Document };
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlIncludeNode"/> 的语法。
        /// </summary>
        /// <param name="path">引用的路径。可以是一个 <see cref="Sofire.Data.XSql.IXSqlNode"/> 的名称，或 *.xsql 文件的路径。</param>
        /// <param name="owner">引用路径的文档。默认为 null 值，表示当前文档。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlIncludeNode"/>。</returns>
        public IXSqlIncludeNode Include(string path, string owner)
        {
            return new XSqlIncludeNode() { Path = path, Document = this._Document, Owner = owner };
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlParametersNode"/> 的语法。
        /// </summary>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlParametersNode"/>。</returns>
        public IXSqlParametersNode Parameters(params IXSql[] children)
        {
            var node = new XSqlParametersNode() { Document = this._Document };
            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlParametersNode"/> 的语法。
        /// </summary>
        /// <param name="test">测试的表达式。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlParametersNode"/>。</returns>
        public IXSqlSwitchNode Switch(string test, params IXSql[] children)
        {
            XSqlSwitchNode node = new XSqlSwitchNode()
            {
                Test = test,
                Document = this._Document,
            };

            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlCaseNode"/> 的语法。
        /// </summary>
        /// <param name="test">测试的表达式。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlCaseNode"/>。</returns>
        public IXSqlCaseNode Case(string test, params IXSql[] children)
        {
            XSqlCaseNode node = new XSqlCaseNode()
            {
                Test = test,
                Document = this._Document,
            };

            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlDefaultNode"/> 的语法。
        /// </summary>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlDefaultNode"/>。</returns>
        public IXSqlDefaultNode Default(params IXSql[] children)
        {
            XSqlDefaultNode node = new XSqlDefaultNode()
            {
                Document = this._Document,
            };

            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlTrimNode"/> 的语法。
        /// </summary>
        /// <param name="prefix">指示当子集合的内容不为空时添加的字首。</param>
        /// <param name="trim">移除所有前导匹配项和尾部匹配项，可为 null 值。</param>
        /// <param name="children">子集合。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlTrimNode"/>。</returns>
        public IXSqlTrimNode Trim(string prefix, string trim, params IXSql[] children)
        {
            XSqlTrimNode node = new XSqlTrimNode()
            {
                Prefix = prefix,
                Trim = trim,
                Document = this._Document,
            };

            this.AppendChildren(node, children);
            return node;
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlExpressionNode"/> 的语法。
        /// </summary>
        /// <param name="name">表达式的名称。</param>
        /// <param name="expression">表达式正文。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlExpressionNode"/>。</returns>
        public IXSqlExpressionNode Expression(string name, string expression)
        {
            return new XSqlExpressionNode()
            {
                Name = name,
                Expression = expression
            };
        }

        /// <summary>
        /// 生成 <see cref="Sofire.Data.XSql.IXSqlParameterNode"/> 的语法。
        /// </summary>
        /// <param name="name">参数名称。</param>
        /// <param name="to">参数新名称。</param>
        /// <param name="required">参数的必要性。</param>
        /// <param name="direction">参数的输入输出类型。</param>
        /// <returns>返回一个 <see cref="Sofire.Data.XSql.IXSqlParameterNode"/>。</returns>
        public IXSqlParameterNode Parameter(string name, string to, bool required, System.Data.ParameterDirection direction)
        {
            return new XSqlParameterNode()
            {
                Name = name,
                To = to,
                Required = required,
                Direction = direction
            };
        }

        #endregion

    }
}
